package com.zdf.license.creator.model;

import com.zdf.license.core.model.LicenseCustomManager;
import com.zdf.license.core.model.LicenseResult;
import de.schlichtherle.license.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import javax.security.auth.x500.X500Principal;
import java.io.File;
import java.text.MessageFormat;
import java.util.prefs.Preferences;

/**
 * 系统软件证书生成管理器
 */
@Slf4j
@AllArgsConstructor
public class LicenseCreatorManager {

    private final LicenseCreatorParam param;

    /**
     * 生成License证书
     * @return GxLicenseResult 证书生成结果
     */
    public LicenseResult generateLicense(){
        try {
            // 1、根据外部传入的创建Lic的参数信息初始化lic参数（秘钥部分）
            LicenseParam licenseParam = initLicenseParam(param);
            // 2、根据外部传入的创建Lic的属性信息初始化lic内容（除了truelicense自带的还包括自己定义的）
            LicenseContent licenseContent = initLicenseContent(param);
            // 3、构建Lic管理器
            LicenseManager licenseManager = new LicenseCustomManager(licenseParam);
            // 4、根据param传入的lic生成的路径创建空文件
            File licenseFile = new File(this.param.getLicensePath());
            // 5、通过Lic管理器，将内容写入Lic文件中
            licenseManager.store(licenseContent, licenseFile);
            return LicenseResult.success("证书生成成功！",licenseContent);
        }catch (Exception e){
            String message = MessageFormat.format("证书生成失败！：{0}", param);
            log.error(message, e);
            return LicenseResult.error(message,e);
        }
    }

    public byte[] create(){
        byte[] licenseInfo = null;
        try {
            // 1、根据外部传入的创建Lic的参数信息初始化lic参数（秘钥部分）
            LicenseParam licenseParam = initLicenseParam(param);
            // 2、根据外部传入的创建Lic的属性信息初始化lic内容（除了truelicense自带的还包括自己定义的）
            LicenseContent licenseContent = initLicenseContent(param);
            // 3、构建Lic管理器
            LicenseManager licenseManager = new LicenseCustomManager(licenseParam);
            // 4、通过Lic管理器，将内容写入Lic文件中
            licenseInfo = licenseManager.create(licenseContent);
        }catch (Exception e){
            String message = MessageFormat.format("证书生成失败！：{0}", param);
            log.error(message, e);
        }
        return licenseInfo;
    }

    /** 证书的发行者和主体字段信息 */
    private final static X500Principal DEFAULT_HOLDER_AND_ISSUER = new X500Principal("CN=iie, OU=iie, O=iie, L=iie, ST=iie, C=iie");

    /**
     * 初始化证书内容信息对象
     * @param param GxLicenseCreatorParam 生成证书参数
     * @return LicenseContent 证书内容
     */
    public static LicenseContent initLicenseContent(LicenseCreatorParam param){
        LicenseContent licenseContent = new LicenseContent();
        licenseContent.setHolder(DEFAULT_HOLDER_AND_ISSUER);
        licenseContent.setIssuer(DEFAULT_HOLDER_AND_ISSUER);
        /* 设置证书名称 */
        licenseContent.setSubject(param.getSubject());
        /* 设置证书有效期 */
        licenseContent.setIssued(param.getIssuedTime());
        /* 设置证书生效日期 */
        licenseContent.setNotBefore(param.getIssuedTime());
        /* 设置证书失效日期 */
        licenseContent.setNotAfter(param.getExpiryTime());
        /* 设置证书用户类型 */
        licenseContent.setConsumerType(param.getConsumerType());
        /* 设置证书用户数量 */
        licenseContent.setConsumerAmount(param.getConsumerAmount());
        /* 设置证书描述信息 */
        licenseContent.setInfo(param.getDescription());
        /* 设置证书扩展信息（对象 -- 额外的ip、mac、cpu等信息） */
        licenseContent.setExtra(param.getExtraParam());
        return licenseContent;
    }
    /**
     * <p>初始化证书生成参数</p>
     * @param param GxLicenseCreatorParam 生成证书参数
     * @return LicenseParam 证书参数
     */
    public static LicenseParam initLicenseParam(LicenseCreatorParam param){
        Preferences preferences = Preferences.userNodeForPackage(LicenseCreator.class);
        /* 设置对证书内容加密的秘钥 */
        CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());
        KeyStoreParam privateStoreParam = new DefaultKeyStoreParam(LicenseCreator.class
                ,param.getPrivateKeysStorePath()
                ,param.getPrivateAlias()
                ,param.getStorePass()
                ,param.getKeyPass());
        return new DefaultLicenseParam(param.getSubject(),preferences,privateStoreParam,cipherParam);
    }
}
